#ifndef VSqlNode_H
#define VSqlNode_H

#include "VSqlQuery.h"

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

class VSqlNode
{
public:
	VSqlNode()
		:m_idNode				("idNode",QVariant::Int)
		,m_idNodeParent	("idNodeParent",QVariant::Int)
		,m_refIdItem		("refIdItem",QVariant::Int)
		,m_refIdRec			("refIdRec",QVariant::Int)
	{}

	void setIdNode(const QVariant &v) { m_idNode.setValue(v);}
	QSqlField idNode() const { return m_idNode;}
	QSqlField *idNodePtr() { return &m_idNode;}

	void setIdNodeParent(const QVariant &v) { m_idNodeParent.setValue(v);}
	QSqlField idNodeParent() const { return m_idNodeParent;}
	QSqlField *idNodeParentPtr() { return &m_idNodeParent;}

	void setRefIdItem(const QVariant &v) { m_refIdItem.setValue(v);}
	QSqlField refIdItem() const { return m_refIdItem;}
	QSqlField *refIdItemPtr() { return &m_refIdItem;}

	void setRefIdRec(const QVariant &v) { m_refIdRec.setValue(v);}
	QSqlField refIdRec() const { return m_refIdRec;}
	QSqlField *refIdRecPtr() { return &m_refIdRec;}

	bool isNull() const { return m_idNode.isNull();}
	
	VSqlFieldList fieldList() const
	{
		return VSqlFieldList()
			<< m_idNode
			<< m_idNodeParent
			<< m_refIdItem
			<< m_refIdRec;
	}

	VSqlFieldPtrList fieldPtrList()
	{
		return VSqlFieldPtrList()
			<< &m_idNode
			<< &m_idNodeParent
			<< &m_refIdItem
			<< &m_refIdRec;
	}

	void setValues(const VSqlSharedRecordPtr &r) { VSqlQuery_recordToFieldsPtr(r,fieldPtrList());}
	void setRecord(VSqlSharedRecordPtr &r) const;

	static QString tableName() { return "VidNode";}
	static QSqlField pos() { return QSqlField("pos",QVariant::Int);}
	static QSqlField status() { return QSqlField("status",QVariant::Int);}

private:
	QSqlField m_idNode;
	QSqlField m_idNodeParent;
	QSqlField m_refIdItem;
	QSqlField m_refIdRec;
};

///////////////////////////////////////////////////////////////////////////////

class VSqlNode_insert
{
public:
	VSqlNode_insert(const QSqlDatabase &db);

	QString sql() const { return m_proc.sql();}

	void exec(VSqlNode &sqlNode);
	
private:
	VSqlQuery_procedure m_proc;
};

///////////////////////////////////////////////////////////////////////////////

class VSqlNode_select_byAnd
{
public:
	VSqlNode_select_byAnd(const QSqlDatabase &db) :m_query(db) {}

	void prepare
	(
		const VSqlFieldList &fieldsSelect,
		const VSqlFieldList &fieldsAnd
	);

	QString sql() const { return m_query.sql();}

	void exec(const VSqlFieldList &fieldsAnd) { m_query.exec(fieldsAnd);}
	bool next(VSqlFieldPtrList &fieldsSelect) { return m_query.next(fieldsSelect);}

private:
	VSqlQuery_select m_query;
};

///////////////////////////////////////////////////////////////////////////////

class VSqlNode_hasChildren
{
public:
	VSqlNode_hasChildren(const QSqlDatabase &db);
	
	QString sql() const { return m_query.sql();}

	bool exec(const QVariant &idNode);
	
private:
	VSqlNode_select_byAnd m_query;
};	
	
///////////////////////////////////////////////////////////////////////////////

class VSqlNodeChildren
{
public:
	VSqlNodeChildren() :m_hasChildren(false),m_canFetch(true) {}
	
	void setChildIdNodeList(const QVariantList &v) { m_childIdNodeList = v; m_hasChildren = v.count() > 0;}
	void appendChildIdNode (const QVariant &v) { m_childIdNodeList << v; m_hasChildren = true;}
	QVariantList childIdNodeList() const { return m_childIdNodeList;}

	void setHasChildren(bool v) { m_hasChildren = v;}
	bool hasChildren() const { return m_hasChildren;}
	
	void setCanFetch(bool v) { m_canFetch = v;}
	bool canFetch() const { return m_canFetch;}

private:
	QVariantList m_childIdNodeList;
	bool m_hasChildren;
	bool m_canFetch;
};

///////////////////////////////////////////////////////////////////////////////

class VSqlNodeMap
{
public:
	VSqlNodeMap(const QSqlDatabase &db);
	~VSqlNodeMap() { clear();}

	QSqlDatabase db() const { return m_db;}

	void clear() { m_childrenMap.clear(); m_recordMap.clear();}
	
	QList<VSqlSharedRecordPtr> recordPtrList_byIdNodeList(const QVariantList &idNodeList);
	VSqlSharedRecordPtr recordPtr_byIdNode(const QVariant &idNode);

	QList<VSqlNode> nodeList_byIdNodeList(const QVariantList &idNodeList);
	VSqlNode node_byIdNode(const QVariant &idNode);

	VSqlNodeChildren children_byIdNode(const QVariant &idNode);
	QList<VSqlSharedRecordPtr> childrenRecordPtrList_byIdNode(const QVariant &idNode);
	QList<VSqlNode> childrenNodeList_byIdNode(const QVariant &idNode);

	QList<VSqlSharedRecordPtr> recordPtrList_byRefIdItem(const QVariant &refIdItem,const QVariant &idNodeParent = QVariant());
	QList<VSqlNode> nodeList_byRefIdItem(const QVariant &refIdItem,const QVariant &idNodeParent = QVariant());

	void insertChildren(const QVariant &idNode,const QList<VSqlNode*> &nodeChildListPtr);
	void insertChild   (const QVariant &idNode,VSqlNode *nodeChildPtr);

	bool updateValue(const QVariant &idNode,int column,const QVariant &value);
	
private:
	VSqlNodeChildren selectChildren_byIdNode(const QVariant &idNode);

	QSqlDatabase m_db;
	QMap<quint64,VSqlSharedRecordPtr> m_recordMap;
	QMap<quint64,VSqlNodeChildren> m_childrenMap;
};

///////////////////////////////////////////////////////////////////////////////

#endif
